﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace DecisionFramework.Logging
{
	/// <summary>
	/// Represents an application event. 
	/// </summary>
	/// <remarks>  
    /// <para>
    /// An application event is a significant
    /// event from an application. It is very
    /// similar to an LogEvent but it is arranged
    /// in a way that makes it more understandable
    /// and helpful. It has details such as what happeneded,
    /// where, when, why, and suggested actions.
    /// </para>
	/// Author: Greg Cowin
	/// </remarks> 
	[DataContract]
	public class AppEvent
	{
		public AppEvent()
		{
			Severity = Severity.Info;
            NumberOccurred = 1;
		}

        /// <summary>
        /// If being suppressed, then this keeps track of the 
        /// number that have occurred since suppressed.
        /// </summary>
		[DataMember]
		public int NumberOccurred { get; set; }

        /// <summary>
        /// What happened in the app event.
        /// </summary>
		[DataMember]
		public string WhatHappened { get; set; }

        /// <summary>
        /// Why did the app event happen?
        /// </summary>
		[DataMember]
		public string WhyDidItHappen { get; set; }

        /// <summary>
        /// Where did the app event happen? The class, component, database, etc. 
        /// where the app event happened.
        /// </summary>
		[DataMember]
		public string WhereDidItHappen { get; set; }

        /// <summary>
        /// The implication of the app event. What affect does it have.
        /// </summary>
		[DataMember]
		public string TheImplication { get; set; }

        /// <summary>
        /// The suggested actions for the reader 
        /// of an app event.
        /// </summary>
		[DataMember]
		public string SuggestedActions { get; set; }

        /// <summary>
        /// Additional details.
        /// </summary>
		[DataMember]
		public string Details { get; set; }

        /// <summary>
        /// An optional exception.
        /// </summary>
		public Exception Exception { get; set; }

        /// <summary>
        /// Optional expection text--the stack trace.
        /// </summary>
		[DataMember]
		public string ExceptionText { get; set; }

        /// <summary>
        /// An optional number of allowed events of its class before
        /// published another one.
        /// </summary>
        [DataMember]
        public int? AllowThisNumberBeforeSuppress { get; set; }

        /// <summary>
        /// The number of minutes to suppress if the property: AllowThisNumberBeforeSuppress
        /// is set and has been reached.
        /// </summary>
		[DataMember]
		public int? NumberOfMinutesToSuppress { get; set; }

        /// <summary>
        /// The severity of the app event.
        /// </summary>
		[DataMember]
		public Severity Severity { get; set; }

        /// <summary>
        /// An optional Id that can be used to correlate
        /// other app events.
        /// </summary>
		[DataMember]
		public int CorrelationId { get; set; }

		public override string ToString()
		{
			StringBuilder builder = new StringBuilder();

            builder.Append("What happened");
            if (NumberOccurred > 1) builder.Append(NumberOccurred + " times?\n");
            else builder.Append("?\n");
			builder.Append(WhatHappened);

			if (WhatHappened != null)
			{
				builder.Append("\n\nWhy did it happen?\n");
				builder.Append(WhyDidItHappen);
			}
			if (WhereDidItHappen != null)
			{
				builder.Append("\n\nWhere did it happen?\n");
				builder.Append(WhereDidItHappen);
			}
			if (TheImplication != null)
			{
				builder.Append("\n\nWhat is the implication?\n");
				builder.Append(TheImplication);
			}
			if (SuggestedActions != null)
			{
				builder.Append("\n\nSuggested Action:\n");
				builder.Append(SuggestedActions);
			}
			if (Details != null)
			{
				builder.Append("\n\nDetails:\n");
				builder.Append(Details);
			}
			if (Exception != null)
			{
				builder.Append("\n\nStackTrace:\n");
				builder.Append(Exception.ToString());
				builder.Append("\n");
				builder.Append(Exception.StackTrace);

				if (Exception.InnerException != null)
				{
					builder.Append("\n\nInner StackTrace:\n");
					builder.Append(Exception.InnerException.ToString());
					builder.Append("\n");
					builder.Append(Exception.InnerException.StackTrace);

					if (Exception.InnerException.InnerException != null)
					{
						builder.Append("\n\nInner.Inner StackTrace:\n");
						builder.Append(Exception.InnerException.InnerException.ToString());
						builder.Append("\n");
						builder.Append(Exception.InnerException.InnerException.StackTrace);
					}
				}
			}
			if (ExceptionText != null)
			{
				builder.Append("\n\nStackTrace:\n");
				builder.Append(ExceptionText);
			}

			return builder.ToString();
		}
	}
}
